package
{
	import flash.display.BlendMode;
	import flash.filesystem.FileStream;
	import flash.filesystem.FileMode;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import kag.util.KagResourceDataWrite;
	import kag.util.KagTxtResourcePath;
	import kag.util.KagResourceDataRead;
	import kag.util.map.KagMapGenerator;
	import org.flixel.*;
	import flash.filesystem.File;

	public class PlayState extends FlxState
	{
		// Tileset that works with AUTO mode (best for thin walls)
		[Embed(source = '../res/image/world.png')]private static var auto_tiles:Class;
		
		// Default tilemaps. Embedding text files is a little weird.
		[Embed(source = '../res/default_auto.txt', mimeType = 'application/octet-stream')]private static var default_auto:Class;

		[Embed(source="../res/image/spaceman.png")] private static var ImgSpaceman:Class;
		
		// Some static constants for the size of the tilemap tiles
		private const TILE_WIDTH:uint = 8;
		private const TILE_HEIGHT:uint = 8;
		
		// Box to show the user where they're placing stuff
		private var highlightBox:FlxObject;
		
		// Player modified from "Mode" demo
		private var player:FlxSprite;
		
		// Some interface buttons and text
		private var autoAltBtn:FlxButton;
		private var resetBtn:FlxButton;
		private var quitBtn:FlxButton;
		private var helperTxt:FlxText;
		
		private var tileGroup:FlxGroup = new FlxGroup();
		
		private var _mapData:Array = new Array();
		private var _mapGenerate:KagMapGenerator = null;
		
		private var _showWidth:uint = 0;
		private var _showHeight:uint = 0;
		private var _showScale:uint = 2;
		
		private var _textNotify:FlxText = null;
		private var _systemNotify:FlxText = null;
		
		private var _systemText:String = "System:"
		public function PlayState()
		{
			
		}
		
		override public function create():void
		{
			_showWidth 	= TILE_WIDTH * _showScale ;
			_showHeight	= TILE_HEIGHT * _showScale;
			FlxG.framerate = 50;
			FlxG.flashFramerate = 50;
			
			var kagResPath:KagTxtResourcePath = new KagTxtResourcePath("default_write");
			var filePathString:String = kagResPath.resourcePath;
			
			var dataRead:KagResourceDataRead = new KagResourceDataRead( filePathString );
			var dataString:Object = dataRead.getData();
			var mapString:String = dataString as String;
			initMapData( mapString );
			
			_mapGenerate = new KagMapGenerator( TILE_WIDTH, TILE_HEIGHT, tileGroup,this,2 );
			_mapGenerate.generateMap( mapString, auto_tiles );
			
			
			highlightBox = new FlxObject(0, 0, _showWidth, _showHeight);
			
			setupPlayer();
			setupText();
		}
		
		private function initMapData( mapString:String ):void
		{
			var rowsArray:Array = mapString.split("\n");
			var rowIndex:int = 0;
			for each( var rowData:String in rowsArray )
			{
				var colIndex:int = 0;
				var colArray:Array = rowData.split(",");
				
				var rowArray:Array = new Array();
				for each( var colData:String in colArray )
				{
					rowArray.push( int(colData) );
				}
				_mapData.push( rowArray );
			}
			
			var overFunc:Boolean = false;
		}
		
		private function updateMap( xPos:int, yPos:int ):void
		{
			var colNumber:int = xPos / _showWidth;
			var rowNumber:int = yPos / _showHeight;
			if ( rowNumber < _mapData.length )
			{
				var columnArray:Array = _mapData[rowNumber];
				if ( columnArray.length > colNumber )
				{
					columnArray[colNumber] = 1;
				}
				else
				{
					columnArray = new Array();
					_mapData.push( columnArray );
					updateColumn( columnArray,rowNumber, rowNumber, colNumber );
				}
			}
			else
			{
				var mapRowLength:int = _mapData.length;
				for ( var generateRowIndex:int = 0; generateRowIndex <= rowNumber; generateRowIndex++ )
				{
					var columnArrayNew:Array = null;
					if ( generateRowIndex >= mapRowLength )
					{
						columnArrayNew = new Array();
						_mapData.push( columnArrayNew );
					}
					else
					{
						columnArrayNew = _mapData[generateRowIndex];
					}
					updateColumn( columnArrayNew, generateRowIndex, rowNumber, colNumber );
				}
			}
		}
		private function updateColumn( columnArray:Array, generateRowIndex:int, rowNumber:int, colNumber:int ):void
		{
			var columnLength:int = columnArray.length;
			for ( var generateColIndex:int = 0; generateColIndex <= colNumber; generateColIndex++ )
			{
				if ( generateColIndex >= columnLength )
				{
					columnArray.push( 0 );
				}
				else
				{
				}
				if ( generateColIndex == colNumber && rowNumber == generateRowIndex )
				{
					columnArray[generateColIndex] = 1;
				}
			}
		}
		private function writeMapToFile():void
		{
			var wholeData:String = "";
			for each( var _rowArray:Array in _mapData )
			{
				var _rowData:String = "";
				for each( var _columnDataValue:int in _rowArray )
				{
					_rowData = _rowData + _columnDataValue.toString() + ",";
				}
				var _writeString:String =  _rowData.substr( 0, _rowData.length - 1 );
				_writeString = _writeString + "\n";
				wholeData = wholeData + _writeString;
			}
			if ( wholeData.length > 0 )
			{
				wholeData =  wholeData.substr( 0, wholeData.length - 1 );	
			}
			
			var kagResPath:KagTxtResourcePath = new KagTxtResourcePath("default_write");
			var filePathString:String = kagResPath.resourcePath;
			
			var writeFile:KagResourceDataWrite = new KagResourceDataWrite();
			writeFile.writeDataToFile( filePathString, wholeData );
			
			_systemNotify.text = _systemText + "map update";
		}
		
		override public function update():void
		{
			// Tilemaps can be collided just like any other FlxObject, and flixel
			// automatically collides each individual tile with the object.
			FlxG.collide(player, tileGroup);
			
			var hightLightPoint:FlxPoint = getHightLightBoxPoint();
			highlightBox.x = hightLightPoint.x;
			highlightBox.y = hightLightPoint.y;
			
			if (FlxG.mouse.pressed())
			{
				_mapGenerate.generateTile( auto_tiles, hightLightPoint.x, hightLightPoint.y );
				updateMap( hightLightPoint.x, hightLightPoint.y );
			}
			
			updatePlayer();
			super.update();
		}
		private function getHightLightBoxPoint():FlxPoint
		{
			var flxPoint:FlxPoint = new FlxPoint();
			flxPoint.x = Math.floor(FlxG.mouse.x / _showWidth) * _showWidth;
			flxPoint.y = Math.floor(FlxG.mouse.y / _showHeight) * _showHeight;
			return flxPoint;
		}
		public override function draw():void
		{
			super.draw();
			highlightBox.drawDebug();
		}
		private function setupText():void
		{
			_textNotify = new FlxText( 0, 200, 200, "Press J to save data." );
			add( _textNotify );
			_systemNotify = new FlxText( 0, 220, 200, _systemText );
			add( _systemNotify );
		}
		private function setupPlayer():void
		{
			player = new FlxSprite(64, 220);
			player.loadGraphic(ImgSpaceman, true, true, 16);
			
			//bounding box tweaks
			player.width = 14;
			player.height = 14;
			player.offset.x = 1;
			player.offset.y = 1;
			
			//basic player physics
			player.drag.x = 640;
			player.acceleration.y = 420;
			player.maxVelocity.x = 80;
			player.maxVelocity.y = 160;
			
			//animations
			player.addAnimation("idle", [0]);
			player.addAnimation("run", [1, 2, 3, 0], 12);
			player.addAnimation("jump", [4]);
			
			add(player);
		}
		
		private function updatePlayer():void
		{
			wrap(player);
			
			//MOVEMENT
			player.acceleration.x = 0;
			if(FlxG.keys.LEFT)
			{
				player.facing = FlxObject.LEFT;
				player.acceleration.x -= player.drag.x;
			}
			else if(FlxG.keys.RIGHT)
			{
				player.facing = FlxObject.RIGHT;
				player.acceleration.x += player.drag.x;
			}
			if(FlxG.keys.justPressed("UP") && player.velocity.y == 0)
			{
				player.y -= 1;
				player.velocity.y = -150;
			}
			
			if ( FlxG.keys.justReleased("J" ) )
			{
				writeMapToFile();
			}
			
			//ANIMATION
			if(player.velocity.y != 0)
			{
				player.play("jump");
			}
			else if(player.velocity.x == 0)
			{
				player.play("idle");
			}
			else
			{
				player.play("run");
			}
		}
		
		private function wrap(obj:FlxObject):void
		{
			obj.x = (obj.x + obj.width / 2 + FlxG.width) % FlxG.width - obj.width / 2;
			obj.y = (obj.y + obj.height / 2) % FlxG.height - obj.height / 2;
		}
	}
}
